package org.mytools.dao.mybatis;

import java.util.List;
import java.util.Map;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import org.mytools.dao.Query;
import org.mytools.dao.gener.MapperWrapper;
import org.mytools.spring.ApplicationContextHolder;

public class MapperDaoTemplate<T> extends SqlSessionDaoSupport {

	private String defaultSqlSessionTemplate = "sqlSessionTemplate";

	private int startLine;

	private int limitLine;

	private String orderString;

	private int totalPage;

	private int totalLine;

	private int curPage;

	private int linePerPage;

	public MapperDaoTemplate() {
		this.setSqlSessionTemplate(this.getSqlSessionTemplate());
	}

	public SqlSessionFactory getSqlSessionFactory() {
		return this.getSqlSessionTemplate().getSqlSessionFactory();
	}

	public SqlSessionTemplate getSqlSessionTemplate() {
		return ApplicationContextHolder.getBean(this.defaultSqlSessionTemplate);
	}

	/**
	 * 设置setSqlSessionTemplate
	 * 
	 * @param beanName
	 *            spring配置文件中定义的SqlSessionTemplate的beanName
	 */
	protected void setSqlSessionTemplate(String beanName) {
		this.defaultSqlSessionTemplate = beanName;
		this.setSqlSessionTemplate(this.getSqlSessionTemplate());
	}

	protected int getLinePerPage() {
		return linePerPage;
	}

	protected void setLinePerPage(int linePerPage) {
		this.linePerPage = linePerPage;
	}

	public int getCurPage() {
		return curPage;
	}

	protected void setCurPage(int curPage) {
		this.curPage = curPage;
	}

	protected int getStartLine() {
		return startLine;
	}

	protected void setStartLine(int startLine) {
		this.startLine = startLine;
	}

	protected int getLimitLine() {
		return limitLine;
	}

	protected void setLimitLine(int limitLine) {
		this.limitLine = limitLine;
	}

	protected String getOrderString() {
		return orderString;
	}

	public void setOrderString(String orderString) {
		this.orderString = orderString;
	}

	public int getTotalPage() {
		return totalPage;
	}

	protected void setTotalPage(int totalPage) {
		this.totalPage = totalPage;
	}

	public int getTotalLine() {
		return totalLine;
	}

	protected void setTotalLine(int totalLine) {
		this.totalLine = totalLine;
	}

	public T selectOne() {
		return selectOne(Query.FIND);
	}

	@SuppressWarnings("unchecked")
	public T selectOne(String queryName) {
		return (T) this.getSqlSession().selectOne(
				MapperWrapper.getMapperQuery(this.getClass().getSimpleName(),
						queryName), this);
	}

	public Object selectOne(String queryName, Map<?, ?> paramsMap) {
		return this.getSqlSession().selectOne(
				MapperWrapper.getMapperQuery(this.getClass().getSimpleName(),
						queryName), paramsMap);
	}

	public List<T> selectList() {
		return selectList(Query.FIND);
	}

	@SuppressWarnings("unchecked")
	public List<T> selectList(String queryName) {
		return this.getSqlSession().selectList(
				MapperWrapper.getMapperQuery(this.getClass().getSimpleName(),
						queryName), this);
	}

	public List<?> selectList(String queryName, Map<?, ?> paramsMap) {
		return this.getSqlSession().selectList(
				MapperWrapper.getMapperQuery(this.getClass().getSimpleName(),
						queryName), paramsMap);
	}

	public int selectCount(String queryName) {
		return (Integer) this.getSqlSession().selectOne(
				MapperWrapper.getMapperQuery(this.getClass().getSimpleName(),
						queryName), this);
	}

	public int selectCount() {
		return selectCount(Query.COUNT);
	}

	public List<T> selectPage(String pageQueryName, String countQueryName,
			int curPage, int linePerPage) {
		int count = selectCount(countQueryName);
		int totalPage = (count % linePerPage == 0) ? (count / linePerPage)
				: (Math.abs(count / linePerPage) + 1);

		this.setCurPage(curPage);
		this.setLinePerPage(linePerPage);
		this.setTotalPage(totalPage);
		this.setTotalLine(count);
		this.setStartLine((curPage - 1) * linePerPage);
		this.setLimitLine(linePerPage);

		return selectList(pageQueryName);
	}

	public List<T> selectPage(int curPage, int linePerPage) {
		return selectPage(Query.PAGE, Query.COUNT, curPage, linePerPage);
	}

	/**
	 * 以startLine开始，取limitLine条记录，支持排序操作
	 * 
	 * @param startLine
	 *            开始的行号，以0开始计数
	 * @param limitLine
	 *            取多少条记录
	 * @return
	 */
	public List<T> selectLimit(int startLine, int limitLine) {
		return selectLimit(Query.LIMIT, startLine, limitLine);
	}

	public List<T> selectLimit(String limitQueryName, int startLine,
			int limitLine) {
		this.setStartLine(startLine);
		this.setLimitLine(limitLine);
		return selectList(limitQueryName);
	}

	public int save() {
		return this.getSqlSession().insert(
				MapperWrapper.getMapperQuery(this.getClass().getSimpleName(),
						Query.SAVE), this);
	}

	public void saveBatch(List<T> list) {
		for (T t : list) {
			this.getSqlSession().insert(
					MapperWrapper.getMapperQuery(this.getClass()
							.getSimpleName(), Query.SAVE), t);
		}
	}

	public int update() {
		return this.getSqlSession().update(
				MapperWrapper.getMapperQuery(this.getClass().getSimpleName(),
						Query.UPDATE), this);
	}

	public void updateBatch(List<T> list) {
		for (T t : list) {
			this.getSqlSession().update(
					MapperWrapper.getMapperQuery(this.getClass()
							.getSimpleName(), Query.UPDATE), t);
		}
	}

	public int delete() {
		return this.getSqlSession().delete(
				MapperWrapper.getMapperQuery(this.getClass().getSimpleName(),
						Query.DELETE), this);
	}

	public void deleteBatch(List<T> list) {
		for (T t : list) {
			this.getSqlSession().delete(
					MapperWrapper.getMapperQuery(this.getClass()
							.getSimpleName(), Query.DELETE), t);
		}
	}

}
